package fr.asip.cps3.exemple.modele.traitements.fonctionsPKCS11.objets;

import java.util.LinkedHashMap;

import org.apache.log4j.Logger;

import iaik.pkcs.pkcs11.wrapper.CK_ATTRIBUTE;
import iaik.pkcs.pkcs11.wrapper.PKCS11;
import iaik.pkcs.pkcs11.wrapper.PKCS11Constants;
import iaik.pkcs.pkcs11.wrapper.PKCS11Exception;
import fr.asip.cps3.exemple.modele.exceptions.ExceptionProgrammeExemple;
import fr.asip.cps3.exemple.modele.exceptions.ExceptionTraitement;
import fr.asip.cps3.exemple.modele.resultats.Resultat;
import fr.asip.cps3.exemple.modele.resultats.ResultatInfo;
import fr.asip.cps3.exemple.modele.traitements.util.TraitementsUtil;

/**
 * Classe de traitement : Création d'un objet de données applicatives
 *
 */
public class CreerObjet{

	/**
	 * Le loggeur
	 */
	private static Logger log = Logger.getLogger(CreerObjet.class);
	
	/**
	 * Renvoie le résultat de l'opération
	 * @param librairie Librairie PKCS#11 à utiliser
	 * @param idSession Identifiant de la session
	 * @param libelle Libellé de l'objet
	 * @param données Données applicatives de l'objet
	 * @return Résultat de l'opération
	 * @throws ExceptionTraitement
	 */
	public static Resultat traitementP11(PKCS11 librairie, long idSession, String libelle, String donnees) throws ExceptionTraitement {

		try {
		
			if(librairie != null) {
			
				ResultatInfo resultat = null;
				LinkedHashMap<String,String> infos = new LinkedHashMap<String,String>();
				resultat = new ResultatInfo("Création de l'objet \""+libelle+"\" (C_CreateObject)");
				resultat.setInfos(infos);
				
				if(libelle != null && donnees != null) {
				
					// Construction de l'objet
					CK_ATTRIBUTE[] attributes = new CK_ATTRIBUTE[5];
					for(int i = 0; i < 5; i++)
						attributes[i] = new CK_ATTRIBUTE();
					attributes[0].type = PKCS11Constants.CKA_CLASS;				
					attributes[0].pValue = PKCS11Constants.CKO_DATA;
					attributes[1].type = PKCS11Constants.CKA_TOKEN;				
					attributes[1].pValue = PKCS11Constants.TRUE;
					attributes[2].type = PKCS11Constants.CKA_APPLICATION;				
					attributes[2].pValue = "ProgrammeExemple";
					attributes[3].type = PKCS11Constants.CKA_LABEL;				
					attributes[3].pValue = libelle.toCharArray();
					attributes[4].type = PKCS11Constants.CKA_VALUE;				
					attributes[4].pValue = TraitementsUtil.getOctetsSansFormatage(donnees);
				
					
					try {
						
						// Traitements à tester
						long idObjet = librairie.C_CreateObject(idSession, attributes);
						infos.put("Identifiant de l'objet",Long.toString(idObjet));
						
					} catch (PKCS11Exception e) {
						
						log.info("Operation echouee : "+TraitementsUtil.retranscritCodeRetour(e.getErrorCode()));
						resultat.setCodeRetour(e.getErrorCode());
						
					}

					return resultat;
					  
				}  else {
					
					// Si le libelle et/ou les données sont null il est impossible de réaliser l'opération
					log.error("Le libelle et/ou les données sont nuls");
					throw new ExceptionTraitement(ExceptionProgrammeExemple.TYPE_TRAITEMENT_OBJETS_CREER, "Le libelle et/les données sont nuls");				
					
				}
			
			} else {
				
				// Si la librairie est nulle il est impossible de réaliser l'opération
				log.error("La librairie est nulle");
				throw new ExceptionTraitement(ExceptionProgrammeExemple.TYPE_TRAITEMENT_OBJETS_CREER, "La librairie est nulle");
				
			}
			
		} catch (Throwable t) {
			
			// Si une erreur Traitement a été rencontrée on lève l'exception
			if(t instanceof ExceptionTraitement)
				throw (ExceptionTraitement)t;
			
			// Si une erreur inattendue est survenue on la logue et on la lève
			log.error("Une erreur inattendue est survenue : "+ExceptionProgrammeExemple.getStacktrace(t));
			throw new ExceptionTraitement(ExceptionProgrammeExemple.TYPE_TRAITEMENT_OBJETS_CREER, "Une erreur inattendue est survenue");
			
		}
		
	}
}
